<?php
/**
 * @author Martin Scotta <martinscotta@gmail.com>
 */

/**
 * 
 */
class LiteUrl {
	
	/**
	 * @var string
	 */
	const SCHEME_HTTP = 'http';
	
	/**
	 * @var string
	 */
	const SCHEME_HTTPS = 'https';
	
	/**
	 * Puerto estandard HTTP
	 * @var integer
	 */
	const PORT_HTTP = 80;
	
	/**
	 * Puerto estandard HTTPS para conexiones cifradas
	 * @var integer
	 */
	const PORT_HTTPS = 443;
	
	/**
	 * @param string $url
	 * @return LiteUrl
	 * @throws LiteException
	 */
	static function parseString($url) {
		$pieces = parse_url($url);
		
		if( false === $pieces ) {
			throw new LiteException('Unable to parse URL');
		}
		
		foreach($pieces as $type => $value) {
			$pieces[$type] = LiteString::toString( $value ); 	
		}
		
		return $pieces;
	}
	
	/**
	 * @var LiteString
	 */
	private $scheme;
	
	/**
	 * @var LiteString
	 */
	private $user;
	
	/**
	 * @var LiteString
	 */
	private $pass;
	
	/**
	 * @var LiteString
	 */
	private $host;
	
	/**
	 * @var int
	 */
	private $port;
	
	/**
	 * @var LiteString
	 */
	private $path;
	
	/**
	 * @var LiteString
	 */
	private $query;
	
	/**
	 * @var LiteString
	 */
	private $fragment;
	
	/**
	 * @param string $url
	 * 
	 * @throws LiteException
	 */
	function __construct($url='/') {
		foreach(self::parseString($url) as $type => $value) {
			if( $value->notEmpty() ) {
				$this->{$type} = (string) $value;
			}
		}
	}
	
	/**
	 * @return boolean
	 */
	function isPortDefault(){
		if( !$this->port ){
			return true;
		}
		return $this->getDefaultPort() === $this->port;
	}
	
	/**
	 * @return integer
	 */
	function getDefaultPort() {
		switch($this->scheme) {
			case self::SCHEME_HTTP:
				return self::PORT_HTTP;
			case self::SCHEME_HTTPS:
				return self::PORT_HTTPS;
		}
		if( $this->port ) {
			return $this->port;
		}
	}
	
	/**
	 * @return string
	 */
	function __toString() {
		$host = '';
		if( $this->scheme && $this->host ) {
			$port = '';
			if( !$this->isPortDefault()) {
				$port = ':' . $this->port;
			}
			$user = '';
			if($this->user) {
				$user = $this->user;
				if($this->pass) {
					$user .= ':' . $this->pass;
				}
				$user .= '@';
			}
			$host = $this->scheme . '://' . $user . $this->host. $port ;	
		}
		
		$query = '';
		if( $this->query){
			$query = '?' . $this->query;
		}
		
		$fragment = '';
		if($this->fragment){
			$fragment = '#' . $this->fragment;
		}
		return $host . $this->path. $query . $fragment;
	}
	
	/**
	 * @return LiteString
	 */
	function getScheme(){
		return LiteString::toString( $this->scheme );
	}

	/**
	 * @param string $scheme
	 */
	function setScheme($scheme){
		return $this->scheme = (string) $scheme;
	}

	/**
	 * @return LiteString
	 */
	function getUser(){
		return LiteString::toString( $this->user );
	}

	/**
	 * @param string $user
	 */
	function setUser($user){
		return $this->user = (string) $user;
	}

	/**
	 * @return LiteString
	 */
	function getPass(){
		return LiteString::toString( $this->pass );
	}

	/**
	 * @param string $pass
	 */
	function setPass($pass){
		return $this->pass = (string) $pass;
	}

	/**
	 * @return LiteString
	 */
	function getHost(){
		return LiteString::toString( $this->host );
	}

	/**
	 * @param string $host
	 */
	function setHost($host){
		return $this->host = (string) $host;
	}

	/**
	 * @return int
	 */
	function getPort(){
		return $this->port;
	}

	/**
	 * @param int $port 
	 */
	function setPort($port){
		return $this->port = (int) $port;
	}

	/**
	 * @return LiteString
	 */
	function getPath(){
		return LiteString::toString( $this->path );
	}

	/**
	 * @param string $path
	 */
	function setPath($path){
		// TODO: DirectoryUtils::fixPath
		return $this->path = (string) $path;
	}

	/**
	 * @return LiteString
	 */
	function getQuery(){
		return LiteString::toString( $this->query );
	}

	/**
	 * @param string $query
	 */
	function setQuery($query){
		return $this->query = (string) $query;
	}

	/**
	 * @return LiteString
	 */
	function getFragment(){
		return LiteString::toString( $this->fragment );
	}

	/**
	 * @param string $fragment
	 */
	function setFragment($fragment){
		return $this->fragment = (string) $fragment;
	}
}
